package com.spark.actions.fin.gld;

import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.ibatis.session.SqlSession;

import com.spark.actions.sys.DefaultAction;
import com.spark.core.Message;
import com.spark.core.SparkContext;

@SuppressWarnings("unchecked")
public class AccountsAction extends DefaultAction {
	
	public static final String FIELD_ACCOUNT_ID = "ACCOUNT_ID";
	public static final String FIELD_ACCOUNT_CODE = "ACCOUNT_CODE";
	public static final String FIELD_ACCOUNT_NAME = "ACCOUNT_NAME";
	public static final String FIELD_ACCOUNT_TYPE = "ACCOUNT_TYPE";
	public static final String FIELD_DC = "DC";
	public static final String FIELD_CURRENCY = "CURRENCY";
	public static final String FIELD_AUXILIARY_ITEM = "AUXILIARY_ITEM";
	public static final String FIELD_IS_ADJUST_RATE = "IS_ADJUST_RATE";
	public static final String FIELD_PARENT_ACCOUNT_CODE = "PARENT_ACCOUNT_CODE";
	public static final String FIELD_PARENT_ACCOUNT_ID = "PARENT_ACCOUNT_ID";
	public static final String FIELD_ACCOUNT_CATEGORY_ID = "ACCOUNT_CATEGORY_ID";
	public static final String FIELD_ACCOUNT_CATEGORY_NAME = "ACCOUNT_CATEGORY_NAME";
	
	private static final Pattern PATTERN_ACCOUNT_CODE = Pattern.compile("^[0-9]{4}(\\.([0-9]{2})){0,3}$");
	
	private static final String VALID_ACCOUNT_CODE = "科目编码结构为4.2.2.2,请正确输入科目编码!";
	private static final String VALID_ACCOUNT_NAME = "科目名称不能为空!";
	private static final String VALID_ACCOUNT_CODE_CONFLICTING = "存在相同的科目编码!";
	private static final String VALID_ACCOUNT_CODE_NO_PARENT_TITLE = "科目编码错误";
	private static final String VALID_ACCOUNT_CODE_NO_PARENT = "在当前分类中找不到上层科目编码!";
	private static final String VALID_ACCOUNT_NO_REMOVE = "有下级科目不能删除!";
	
	
	private static final String SQL_SELECT_STATEMENT = "gld_accounts.select";
	private static final String SQL_CREATE_STATEMENT = "gld_accounts.insert";
	private static final String SQL_UPDATE_STATEMENT = "gld_accounts.update";
	private static final String SQL_DELETE_STATEMENT = "gld_accounts.delete";
	private static final String SQL_SELECT_CHILDREN_STATEMENT = "gld_accounts.selectChildrenCount";
	private static final String SQL_SELECT_PARENT_ACCOUNT_STATEMENT = "gld_accounts.selectParentAccount";
	private static final String SQL_CLEAR_PARENT_ACCOUNT_STATEMENT = "gld_accounts.clearParentAccount";
	
	
	/**
	 * 查询科目
	 * 
	 * @param context
	 * @throws Exception
	 */
	public void query(SparkContext context) throws Exception {
		doQuery(context, SQL_SELECT_STATEMENT);
	}
	
	/**
	 * 创建科目.
	 * @param context
	 * @throws Exception
	 */
	
	public void create(SparkContext context) throws Exception {
		doExecute(context, SQL_CREATE_STATEMENT, ACTION_INSERT);
	}
	
	/**
	 * 更新科目.
	 * @param context
	 * @throws Exception
	 */
	public void update(SparkContext context) throws Exception {
		doExecute(context, SQL_UPDATE_STATEMENT, ACTION_UPDATE);
	}
	
	/**
	 * 删除科目.
	 * 
	 * @param context
	 * @throws Exception
	 * TODO:判断当前科目是否已经被使用? 
	 */
	public void delete(SparkContext context) throws Exception {
		doExecute(context, SQL_DELETE_STATEMENT, ACTION_DELETE);
	}
	
	
	/**
	 * 处理币种和期末调汇
	 * @param map
	 */
	private void processAdjustRate(Map map){
		String currency = (String)map.get(FIELD_CURRENCY);
		if(CurrencyAction.DEFAULT_STANDARD_MONEY.equalsIgnoreCase(currency)) {
			map.put(FIELD_IS_ADJUST_RATE, 0);
		}
	}
	
	/**
	 * 创建科目
	 */
	protected void doInsert(SparkContext context,SqlSession sqlSession, String statement, Map map,Message message){
		String accountCode = (String) map.get(FIELD_ACCOUNT_CODE);
		processAdjustRate(map);
		if(accountCode.indexOf(".")!=-1){
			String parentCode = accountCode.substring(0,accountCode.lastIndexOf("."));
			map.put(FIELD_PARENT_ACCOUNT_CODE, parentCode);
			Map parent = (Map)sqlSession.selectOne(SQL_SELECT_PARENT_ACCOUNT_STATEMENT, map);
			if(parent != null) {				
				extendParentAndClearParent(context,parent,map,sqlSession,message);
				map.put(FIELD_PARENT_ACCOUNT_ID, parent.get(FIELD_ACCOUNT_ID));
				super.doInsert(context,sqlSession, statement, map, message);
			}else{
				message.setWarning(VALID_ACCOUNT_CODE_NO_PARENT_TITLE,VALID_ACCOUNT_CODE_NO_PARENT);
				message.setWidth(300);
				message.setHeiht(150);
			}
		}else {
			map.put(FIELD_PARENT_ACCOUNT_ID, 0);
			super.doInsert(context,sqlSession, statement, map, message);
		}
	}
	
	/**
	 * 继承父节点配置，同时清空父节点配置
	 * @param parent
	 * @param child
	 * @param sqlSession
	 * @param message
	 */
	private void extendParentAndClearParent(SparkContext context,Map parent, Map child,SqlSession sqlSession,Message message) {
		initModel(context,parent);
		Integer childrenCount = (Integer)sqlSession.selectOne(SQL_SELECT_CHILDREN_STATEMENT, parent);
		if(childrenCount == 0) {			
			child.put(FIELD_DC, parent.get(FIELD_DC));
			child.put(FIELD_CURRENCY, parent.get(FIELD_CURRENCY));
			child.put(FIELD_AUXILIARY_ITEM, parent.get(FIELD_AUXILIARY_ITEM));
			child.put(FIELD_ACCOUNT_CATEGORY_ID, parent.get(FIELD_ACCOUNT_CATEGORY_ID));
			child.put(FIELD_ACCOUNT_CATEGORY_NAME, parent.get(FIELD_ACCOUNT_CATEGORY_NAME));
			super.doUpdate(context,sqlSession, SQL_CLEAR_PARENT_ACCOUNT_STATEMENT, parent, message);
		}
	}
	
	
	/**
	 * 更新科目
	 */
	protected void doUpdate(SparkContext context,SqlSession sqlSession, String statement, Map map,Message message){
		Integer childrenCount = (Integer)sqlSession.selectOne(SQL_SELECT_CHILDREN_STATEMENT, map);
		//有下级科目
		if(childrenCount>0){
			map.remove(FIELD_ACCOUNT_CODE);
			map.remove(FIELD_CURRENCY);
			map.remove(FIELD_AUXILIARY_ITEM);
			map.remove(FIELD_IS_ADJUST_RATE);
			//下级科目有引用，不能修改<科目性质><余额方向>	
			super.doUpdate(context,sqlSession, statement, map, message);
		//无下级科目	
		}else {
			processAdjustRate(map);
			//科目有引用，不能修改<科目性质><余额方向>，不能删除引用<币种>,不能修改<核算项目>
			String accountCode = (String) map.get(FIELD_ACCOUNT_CODE);
			if(accountCode != null && accountCode.indexOf(".")!=-1){
				String parentCode = accountCode.substring(0,accountCode.lastIndexOf("."));
				map.put(FIELD_PARENT_ACCOUNT_CODE, parentCode);
				Map parent = (Map)sqlSession.selectOne(SQL_SELECT_PARENT_ACCOUNT_STATEMENT, map);
				if(parent != null) {
					extendParentAndClearParent(context,parent,map,sqlSession,message);
					map.put(FIELD_PARENT_ACCOUNT_ID, parent.get(FIELD_ACCOUNT_ID));
					super.doUpdate(context,sqlSession, statement, map, message);
				}else{
					message.setWarning(VALID_ACCOUNT_CODE_NO_PARENT_TITLE,VALID_ACCOUNT_CODE_NO_PARENT);
					message.setWidth(300);
					message.setHeiht(150);
				}
			}else {
				map.put(FIELD_PARENT_ACCOUNT_ID, 0);
				super.doUpdate(context,sqlSession, statement, map, message);
			}			
		}
	}
	
	
	/**
	 * 删除科目
	 */
	protected void doDelete(SparkContext context,SqlSession sqlSession,String statement, List list, Message message){
		if(list!=null && list.size() > 0){
			Map map = (Map)list.get(0);
			Integer childrenCount = (Integer)sqlSession.selectOne(SQL_SELECT_CHILDREN_STATEMENT, map);
			//有下级科目
			if(childrenCount>0){
				message.setWarning(VALID_ACCOUNT_NO_REMOVE);
				message.setWidth(300);
				message.setHeiht(150);
			}else {
				sqlSession.delete(statement, map);
			}
		}
		message.setResult(list);
	}
	
	
	protected boolean validateInset(Map map, Message message){
		return isNotNullAndRestrict(map.get(FIELD_ACCOUNT_CODE),PATTERN_ACCOUNT_CODE, message,VALID_ACCOUNT_CODE)&&
			   isNotNull(map.get(FIELD_ACCOUNT_NAME), message,VALID_ACCOUNT_NAME);
	}
	
	protected boolean validateUpdate(Map map, Message message){
		return isNotEmpty(map.get(FIELD_ACCOUNT_NAME), message,VALID_ACCOUNT_NAME) && 
		       isNullOrRestrict(map.get(FIELD_ACCOUNT_CODE),PATTERN_ACCOUNT_CODE,  message,VALID_ACCOUNT_CODE);
	}
	
	
	protected void writeConflictingMessage(Map map, Message message){
		message.setWarning(VALID_ACCOUNT_CODE_CONFLICTING);
		message.setWidth(300);
		message.setHeiht(150);
	}
	
	
	
}
